package agent.demo;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;

public class ClassFileTransformerDemo implements ClassFileTransformer {

    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
            byte[] classfileBuffer) {
        //System.out.println("========================className: " + className);
        if (!className.equalsIgnoreCase("agent/app/Dog")) {
            return null;
        }
//        Class<?> clazz = null;
//        try {
//            clazz = loader.loadClass("agent.app.Dog");
//            System.out.println("load clazz: " + clazz.getName());
//            return getClassBytes(clazz);
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
        return getBytesFromFile("D:/ideahome/all-demo/java-agent-demo/agent-demo/target/classes/agent/app/Dog.class");
    }

//    public static void main(String[] args) throws IOException {
//        byte[] classBytes = getClassBytes(ClassFileTransformerDemo.class);
//        System.out.println(classBytes.length);
//    }
    public static byte[] getClassBytes(Class<?> clazz) throws IOException {
        try (InputStream is = clazz.getClassLoader().getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) {
            if (is == null) {
                throw new IOException("Could not find class file for " + clazz.getName());
            }
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int nRead;
            byte[] data = new byte[1024];
            while ((nRead = is.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, nRead);
            }
            buffer.flush();
            return buffer.toByteArray();
        }
    }


    public static byte[] getBytesFromFile(String fileName) {
        File file = new File(fileName);
        try (InputStream is = new FileInputStream(file)) {
            // precondition

            long length = file.length();
            byte[] bytes = new byte[(int) length];

            // Read in the bytes
            int offset = 0;
            int numRead = 0;
            while (offset < bytes.length
                    && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
                offset += numRead;
            }

            if (offset < bytes.length) {
                throw new IOException("Could not completely read file "
                        + file.getName());
            }
            is.close();
            return bytes;
        } catch (Exception e) {
            System.out.println("error occurs in _ClassTransformer!"
                    + e.getClass().getName());
            return null;
        }
    }

}
